import json

from django import http

from django.contrib.auth import login
from django.http import HttpResponse
from django.http import JsonResponse
from django.shortcuts import render, redirect
from django.views import View
from django.http import HttpResponseBadRequest
import re
# Create your views here.
from apps.users.models import User, Address
import logging

from apps.users.utils import generate_verify_email_url
from utils.response_code import RETCODE
from utils.views import LoginRequiredJSONMixin

logger = logging.getLogger('django')
from django.urls import reverse


class RegisterView(View):

    def get(self,request):
        return render(request, 'register.html')

    def post(self, request):
        data = request.POST
        username = data.get('username')
        password = data.get('password')
        password2 = data.get('password2')
        mobile = data.get('mobile')
        allow = data.get('allow')
        sms_code_cli = data.get('sms_code')

        if not all([username, password, password2, mobile, allow,sms_code_cli]):
            return HttpResponseBadRequest('参数不全')
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$',username):
            return HttpResponseBadRequest('用户名不符合规则')
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return HttpResponseBadRequest('密码不符合规则')
        if password2 != password:
            return HttpResponseBadRequest('确认密码不正确')
        if not re.match(r'^1[3456789]\d{9}$', mobile):
            return HttpResponseBadRequest('手机号格式不正确')
        if allow != 'on':
            return HttpResponseBadRequest('您为同意协议')
        from django_redis import get_redis_connection
        try:
            redis_conn = get_redis_connection('code')
            sms_code_server = redis_conn.get('sms_%s'%mobile)
            if sms_code_server is None:
                return HttpResponseBadRequest('短信验证码失效')
            if sms_code_cli != sms_code_server.decode():
                return HttpResponseBadRequest('短信验证码输入错误')
        except Exception as e:
            return HttpResponseBadRequest('链接数据库不成功')

        try:
            user = User.objects.create_user(
                username=username,
                password=password,
                mobile=mobile
            )
            from django.contrib.auth import login
            login(request, user)
            #保存用户登陆状态
        except Exception as e:
            logger.error(e)
            return render(request, 'register.html', context={'register_error':'保存用户数据失败'} )
        return redirect(reverse('contents:index'))
#后端检查用户名是否重复,返回给前端一个count值(json数据)
class UsernameCountView(View):
    def get(self, request, username):
        count = User.objects.filter(username__exact=username).count()
        return JsonResponse({'count':count})

class MobileCountView(View):
    def get(self, request, mobile):
        count = User.objects.filter(mobile__exact=mobile).count()
        return JsonResponse({'count':count})

class LoginView(View):
    def get(self, request):
        return render(request, 'login.html')
    def post(self, request):
        data = request.POST

        username = data.get('username')
        password = data.get('password')
        remembered = data.get('remembered')
        if not all([username, password]):
            return render(request, 'login.html')
        if not re.match(r'^[a-zA-Z0-9-_]{5,20}$',username):
            return HttpResponseBadRequest('用户名不符合规则')
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return HttpResponseBadRequest('密码不符合规则')

        from django.contrib.auth import authenticate

        user = authenticate(username=username, password=password)
        if user is None:
            return render(request,'login.html',{'error':'用户名或者密码错误'})

        login(request,user)

        if remembered != 'on':
            request.session.set_expiry(0)

        if remembered == 'on':
            request.session.set_expiry(None)

        next = request.GET.get('next')


        if next:
            response = redirect(next)
        else:
            response = redirect(reverse('contents:index'))

        # response.set_cookie(key,value,max_age=)
        if remembered != 'on':
            response.set_cookie('username', user.username, max_age=None)
        if remembered == 'on':
            response.set_cookie('username', user.username, max_age=3600*24*15)


        return response

#s首页退出功能是直接调用系统logout方法并删除前端cookie信息
from django.contrib.auth import logout
class LogoutView(View):

    def get(self,request):
        logout(request)

        response = redirect(reverse('contents:index'))
        response.delete_cookie('username')
        return response

from django.contrib.auth.mixins import LoginRequiredMixin

class UserInfoView(LoginRequiredMixin,View):
    def get(self, request):
        """提供个人信息界面"""
        context = {
            'username': request.user.username,
            'mobile': request.user.mobile,
            'email': request.user.email,
            'email_active': request.user.email_active
        }
        return render(request, 'user_center_info.html', context=context)



#添加邮箱后端逻辑实:



class EmailView(LoginRequiredJSONMixin,View):
    import json

    class EmailView(View):
        """添加邮箱"""

        def put(self, request):
            """实现添加邮箱逻辑"""
            # 接收参数
            json_dict = json.loads(request.body.decode())
            email = json_dict.get('email')

            # 校验参数
            if not email:
                return http.HttpResponseBadRequest('缺少email参数')
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('参数email有误')
            from celery_tasks.email.tasks import send_verify_email
            verify_url = generate_verify_email_url(request.user)
            send_verify_email.delay(email, verify_url)

            # 赋值email字段
            try:
                request.user.email = email
                request.user.save()
            except Exception as e:
                logger.error(e)
                return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '添加邮箱失败'})

            # 响应添加邮箱结果
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加邮箱成功'})


#验证邮箱保存结果
from apps.users.utils import check_verify_email_token

class VerifyEmailView(View):
    """验证邮箱"""

    def get(self, request):
        """实现邮箱验证逻辑"""
        # 接收参数
        token = request.GET.get('token')

        # 校验参数：判断token是否为空和过期，提取user
        if not token:
            return http.HttpResponseBadRequest('缺少token')

        user = check_verify_email_token(token)
        if not user:
            return http.HttpResponseBadRequest('无效的token')

        # 修改email_active的值为True
        try:
            user.email_active = True
            user.save()
        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError('激活邮件失败')

        # 返回邮箱验证结果
        return redirect(reverse('users:userinfo'))



from django.views import View
from utils.views import LoginRequiredMixin

class AddressView(LoginRequiredMixin, View):
    """用户收货地址"""

    def get(self, request):
        """提供收货地址界面"""
        login_user = request.user
        addresses = Address.objects.filter(user=login_user,is_deleted=False)
        address_dict_list = []
        for address in addresses:
            address_dict = {
                "id": address.id,
                "title": address.title,
                "receiver": address.receiver,
                "province": address.province.name,
                "province_id": address.province_id,
                "city": address.city.name,
                "city_id": address.city_id,
                "district": address.district.name,
                "district_id": address.district_id,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email
            }
            address_dict_list.append(address_dict)
        context = {
            'default_address_id': login_user.default_address_id,
            'addresses': address_dict_list,
        }




        return render(request, 'user_center_site.html', context=context)

#新增收货地址
class CreateAddressView(LoginRequiredJSONMixin, View):
    def post(self, request):
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.HttpResponseBadRequest('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('参数mobile有误')
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseBadRequest('参数tel有误')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('参数email有误')

        try:
            address = Address.objects.create(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email
            )
            if not request.user.default_address:
                request.user.default_address = address
                request.user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '新增地址失败'})

        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '新增地址成功', 'address': address_dict})

#修改和删除地址

class UpdateDestroyAddressView(LoginRequiredJSONMixin, View):
    """修改和删除地址"""

    def put(self, request, address_id):
        """修改地址"""
        # 接收参数
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 校验参数
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.HttpResponseBadRequest('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('参数mobile有误')
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseBadRequest('参数tel有误')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('参数email有误')

        # 判断地址是否存在,并更新地址信息  前端传来的address_id
        try:
            Address.objects.filter(id=address_id).update(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email
            )
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '更新地址失败'})

        # 构建字典信息
        address = Address.objects.get(id=address_id)

        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        # 响应更新地址结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '更新地址成功', 'address': address_dict})

    def delete(self, request, address_id):
        """删除地址"""
        try:
            # 查询要删除的地址
            address = Address.objects.get(id=address_id)

            # 将地址逻辑删除设置为True
            address.is_deleted = True
            address.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '删除地址失败'})

        # 响应删除地址结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '删除地址成功'})



#设置默认地址
class DefaultAddressView(LoginRequiredJSONMixin, View):
    """设置默认地址"""

    def put(self, request, address_id):
        """设置默认地址"""
        try:
            # 接收参数,查询地址
            address = Address.objects.get(id=address_id)

            # 设置地址为默认地址
            request.user.default_address = address
            request.user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '设置默认地址失败'})

        # 响应设置默认地址结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '设置默认地址成功'})

#修改收货地址标题
class UpdateTitleAddressView(LoginRequiredJSONMixin, View):
    """设置地址标题"""

    def put(self, request, address_id):
        """设置地址标题"""
        # 接收参数：地址标题
        json_dict = json.loads(request.body.decode())
        title = json_dict.get('title')

        try:
            # 查询地址
            address = Address.objects.get(id=address_id)

            # 设置新的地址标题
            address.title = title
            address.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '设置地址标题失败'})

        # 4.响应删除地址结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '设置地址标题成功'})



#修改密码
class ChangePasswordView(LoginRequiredMixin, View):
    """修改密码"""

    def get(self,request):
        return render(request, 'user_center_pass.html')
    def post(self,request):
        def post(self, request):
            """实现修改密码逻辑"""
            # 1.接收参数
            old_password = request.POST.get('old_password')
            new_password = request.POST.get('new_password')
            new_password2 = request.POST.get('new_password2')
            # 2.验证参数
            if not all([old_password, new_password, new_password2]):
                return http.HttpResponseForbidden('缺少必传参数')
            if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password):
                return http.HttpResponseBadRequest('密码最少8位，最长20位')
            if new_password != new_password2:
                return http.HttpResponseBadRequest('两次输入的密码不一致')

            # 3.检验旧密码是否正确
            if not request.user.check_password(old_password):
                return render(request, 'user_center_pass.html', {'origin_password_errmsg': '原始密码错误'})
            # 4.更新新密码
            try:
                request.user.set_password(new_password)
                request.user.save()
            except Exception as e:
                logger.error(e)
                return render(request, 'user_center_pass.html', {'change_password_errmsg': '修改密码失败'})
            # 5.退出登陆,删除登陆信息
            logout(request)
            # 6.跳转到登陆页面
            # response = redirect(reverse('users:login'))
            #
            # response.delete_cookie('username')

            # return response

            return redirect(reverse('users:login'))










